#include "StdAfx.h"

#include "CDIADataWtch.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


CDIAViewItem::CDIAViewItem(IDiaSymbol* psymbolData, IDiaSymbol* psymbolType, DWORD dwBaseAddr)
				:m_dwAddr(INVALID_ADDR)
{
	m_pdiadata=(std::auto_ptr<CDIAData>)(new CDIAData(psymbolData, psymbolType));
	if(INVALID_ADDR!=dwBaseAddr)
	{
		SetBaseAddr(dwBaseAddr);
	}
	
	m_pDataVal=(std::auto_ptr<IDIADataValue>)(CreateDIADataValue(m_pdiadata.get()));

	
}

CDIAViewItem::CDIAViewItem(CDIAData* pdiadata, DWORD dwBaseAddr)
			: m_pdiadata(pdiadata)
			, m_dwAddr(INVALID_ADDR)
{
	if(INVALID_ADDR!=dwBaseAddr)
	{
		SetBaseAddr(dwBaseAddr);
	}
	m_pDataVal=(std::auto_ptr<IDIADataValue>)(CreateDIADataValue(m_pdiadata.get()));
}

BOOL CDIAViewItem::EnumChild(CDIADataWtchEnum** ppEnum, BOOL* pfPtr)
{
	IEnumMemberData* pEnumMemberData;
	if(FALSE==m_pdiadata->EnumMemberData(&pEnumMemberData, pfPtr))
	{
		return FALSE;
	}

	*ppEnum=new CDIADataWtchEnum(pEnumMemberData);
	return TRUE;
}

BOOL CDIAViewItem::SetBaseAddr(DWORD dwBaseAddr, BOOL fFalse)
{
	if(fFalse)
	{
		m_dwAddr=dwBaseAddr;
		return TRUE;
	}
	
	LONG lOffset;
	if(FALSE==m_pdiadata->GetOffset(&lOffset))
	{
		return FALSE;
	}
	else
	{
		m_dwAddr=dwBaseAddr+lOffset;
	}
	return TRUE;
}

BOOL CDIAViewItem::GetAddr(DWORD* pdwAddr)
{
	if(INVALID_ADDR==m_dwAddr)
	{
		return FALSE;
	}

	ASSERT(NULL!=pdwAddr);
	*pdwAddr=m_dwAddr;
	return TRUE;
}

VOID CDIAViewItem::GetAddr(CString* pstrAddr)
{
	if(INVALID_ADDR==m_dwAddr)
	{
		*pstrAddr=_T("");
	}
	else
	{
		pstrAddr->Format(_T("0x%08x"), m_dwAddr);
	}
}

VOID CDIAViewItem::GetOffset(CString* pstrOff)
{
	LONG lOffset;
	if(FALSE!=m_pdiadata->GetOffset(&lOffset))
	{
		pstrOff->Format(_T("0x%x"), lOffset);
	}
	else
	{
		*pstrOff=_T("");
	}
}

VOID CDIAViewItem::GetValue(CString* pstrVal)
{
	if(m_pDataVal.get()==NULL)
	{
		*pstrVal=_T("");
	}
	else
	{
		m_pDataVal->Val2CStr(pstrVal);
	}
}

VOID CDIAViewItem::GetBitInfo(CString* pstrBitPos, CString* pstrBitLen)
{
	if(!m_pdiadata->IsBit())
	{
		*pstrBitPos=_T("");
		*pstrBitLen=_T("");
	}
	else
	{
		DWORD dwBitPos, dwBitLen;
		m_pdiadata->GetBitInfo(&dwBitPos, &dwBitLen);
		pstrBitPos->Format(_T("%d"), dwBitPos);
		pstrBitLen->Format(_T("%d"), dwBitLen);
	}
}

BOOL CDIAViewItem::MemUpdateLocVal(IMemSpace* pIMem)
{
	ASSERT(NULL!=pIMem);
	if(m_pDataVal.get()==NULL)
	{
		return FALSE;
	}

	// no valid address
	if(INVALID_ADDR==m_dwAddr)
	{
		return FALSE;
	}

	return m_pDataVal->MemUpdateVal(pIMem, m_dwAddr);
}

BOOL CDIAViewItem::LocValUpdateMem(IMemSpace* pIMem)
{
	ASSERT(NULL!=pIMem);
	if(m_pDataVal.get()==NULL)
	{
		return FALSE;
	}

	// no valid address
	if(INVALID_ADDR==m_dwAddr)
	{
		return FALSE;
	}

	return m_pDataVal->ValUpdateMem(pIMem, m_dwAddr);
}


/////////////////////////////////////////////////////////
//class CDIADataWtchEnum
//
BOOL CDIADataWtchEnum::Next( CDIAViewItem** ppdiavi)
{
	 CDIAData* pdiaData;
	if(FALSE==m_pEnumMemberData->Next(&pdiaData))
	{
		return FALSE;
	}

	*ppdiavi=new CDIAViewItem(pdiaData, m_dwBaseAddr);
	return TRUE;
}



IDIADataValue* CreateDIADataValue(CDIAData* pdiadata)
{
	IDIADataValue* pIDiaDataValue;
	if(FALSE!=pdiadata->IsBit())
	{
		CDIADataValue<UINT>* p=new CDIADataValue<UINT>;
		pIDiaDataValue=p;
		pdiadata->GetBitInfo(&p->m_dwBitPos, &p->m_dwBitLen);
	}
	else if(FALSE!=pdiadata->IsPtr())
	{
		pIDiaDataValue=new CDIADataValue<UINT>;
	}
	else
	{
		switch (pdiadata->GetBaseType())
		{
		case btChar:
			pIDiaDataValue=new CDIADataValue<char>;
			break;

		case btWChar:
			pIDiaDataValue=new CDIADataValue<WORD>;
			break;

		case btInt:
			pIDiaDataValue=new CDIADataValue<int>;
			break;

		case btUInt:
			pIDiaDataValue=new CDIADataValue<UINT>;
			break;

		case btBool:
			pIDiaDataValue=new CDIADataValue<bool>;
			break;

		case btLong:
			pIDiaDataValue=new CDIADataValue<LONG>;
			break;

		case btULong:
			pIDiaDataValue=new CDIADataValue<ULONG>;
			break;

		case btNoType:
			pIDiaDataValue=NULL;
			break;
			
		default:
			TRACE(_T("the DIADataValue of type:%d not implement now!\r\n"), pdiadata->GetBaseType());
			pIDiaDataValue=NULL;
			break;
		
		}
	}
	return pIDiaDataValue;	
}

